package com.redis.lock.api;

import com.redis.util.SpringContextUtil;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zzm
 * @version V1.0
 * @date 2017-09-26 14:38
 **/
public class RedisCommd {

    public static Long lock(String key, String id, long expire) {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptText("if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1],ARGV[1], 1); " +
                "redis.call('pexpire', KEYS[1], ARGV[2]); return nil; end; " +
                "if (redis.call('hexists', KEYS[1], ARGV[1]) == 1) then redis.call('hincrby', KEYS[1], ARGV[1], 1); " +
                "redis.call('pexpire', KEYS[1], ARGV[2]); return nil; end; return redis.call('pttl', KEYS[1]);");
        script.setResultType(Long.class);
        List<String> list = new ArrayList<>();
        list.add(key);
        StringRedisTemplate redisTemplate = SpringContextUtil.getBean(StringRedisTemplate.class);
        Long result = redisTemplate.execute(script, list, id, expire);
        return result == null ? 0 : result;
    }

    public static Long unlock(String key, String id) {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptText("if (redis.call('exists', KEYS[1]) == 0) then return 0; end; " +
                "if (redis.call('hexists', KEYS[1], ARGV[1]) == 0) then return 0; end; " +
                "local counter = redis.call('hincrby', KEYS[1], ARGV[1], -1); " +
                "if (counter > 0) then return 1; " +
                "else " +
                "redis.call('del', KEYS[1]); return 1; end; return -1;");
        script.setResultType(Long.class);
        List<String> list = new ArrayList<>();
        list.add(key);
        StringRedisTemplate redisTemplate = SpringContextUtil.getBean(StringRedisTemplate.class);
        return redisTemplate.execute(script, list, id);
    }
}
